package com.cj.ai.controller;

import com.cj.ai.constants.MindConstants;
import com.cj.ai.entity.vo.DAVO;
import com.cj.ai.entity.vo.STVO;
import com.cj.ai.repository.ChatHistoryRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.document.Document;
import org.springframework.ai.model.Media;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.core.io.InputStreamResource;
import org.springframework.util.MimeType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;

@RequiredArgsConstructor
@RestController
@RequestMapping("/ai")
public class ChatController {

    private final ChatClient chatClient;
    private final ChatClient aiClient;
    private final ChatClient vClient;
    private final ChatClient tClient;
    private final ChatHistoryRepository chatHistoryRepository;
    private String chatId="";
    private final ChatMemory chatMemory;

    //新建一个get接口返回mind字符串的内容
    @RequestMapping("/getMind")
    public String getMind() {
        List<Message> messages = chatMemory.get(chatId, Integer.MAX_VALUE);
        System.out.println( messages);
        //倒着循环messages 获取所有消息


        for (int i = messages.size() - 1; i >= 0; i--) {
            Message message = messages.get(i);
            if (message.getMessageType().name().equals("ASSISTANT")) {
                 //获取message.getText()的内容种<mindmap_data> 标签之间的内容

                // 1. 先找到闭标签的位置
                int closeTagPos = message.getText().lastIndexOf("</mindmap_data>");
                if (closeTagPos == -1) {
                   continue; // 没有找到闭标签
                }

                // 2. 在闭标签之前查找最近的开始标签
                int openTagPos = message.getText().lastIndexOf("<mindmap_data>", closeTagPos);
                if (openTagPos == -1) {
                    continue; // 没有找到对应的开始标签
                }

                // 3. 计算内容起始位置（开始标签结束位置）
                int contentStart = openTagPos + "<mindmap_data>".length();

                if (contentStart != -1) {
                    MindConstants.mind=message.getText().substring(contentStart, closeTagPos).trim();
                    return message.getText().substring(contentStart, closeTagPos).trim();
                }
            }
        }

        return MindConstants.mind;
    }
    @RequestMapping(value = "/chat", produces = "text/html;charset=utf-8")
    public Flux<String> chat(
            @RequestParam("prompt") String prompt,
            @RequestParam("chatId") String chatId,
            @RequestParam(value = "files", required = false) List<MultipartFile> files) {
        // 1.保存会话id
        chatHistoryRepository.save("chat", chatId);
        // 2.请求模型
        if (files == null || files.isEmpty()) {
            // 没有附件，纯文本聊天
            return textChat(prompt, chatId);
        } else {
            // 有附件，多模态聊天
//            return multiModalChat(prompt, chatId, files);
            //TikaDocumentReader 转 Document
            TikaDocumentReader tikaDocumentReader = null;
            try {
                tikaDocumentReader = new TikaDocumentReader(new InputStreamResource(files.get(0).getInputStream()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            String text = tikaDocumentReader.get().get(0).getText();
            System.out.println( text);
            return chatClient.prompt()
                    .user(p -> p.text(prompt).text( text))
                    .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))
                    .stream()
                    .content();
        }


    }
    @RequestMapping(value = "/cjchat", produces = "text/html;charset=utf-8")
    public Flux<String> cjchat(
            @RequestParam("prompt") String prompt,
            @RequestParam(value = "files", required = false) List<MultipartFile> files) {
        // 1.保存会话id
        chatHistoryRepository.save("chat", "chatId");
        // 2.请求模型
        if (files == null || files.isEmpty()) {
            // 没有附件，纯文本聊天
            return cjtextChat(prompt, "chatId");
        } else {
            // 有附件，多模态聊天
                return multiModalChat(prompt, "chatId", files);
        }

    }
    private Flux<String> cjtextChat(String prompt, String chatId) {
        Flux<String> response = aiClient.prompt()
                .user(prompt)
                .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))
                .stream()
                .content();

        return response;
    }
    private Flux<String> multiModalChat(String prompt, String chatId, List<MultipartFile> files) {


        // 1.解析多媒体
        List<Media> medias = files.stream()
                .map(file -> new Media(
                                MimeType.valueOf(Objects.requireNonNull(file.getContentType())),
                                file.getResource()
                        )
                )
                .toList();
        // 2.请求模型
        return chatClient.prompt()
                .user(p -> p.text(prompt).media(medias.toArray(Media[]::new)))
                .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))
                .stream()
                .content();
    }

    private Flux<String> textChat(String prompt, String chatId) {
        this.chatId=chatId;
        Flux<String> response = chatClient.prompt()
                .user(prompt)

                .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))
                .stream()
                .content();
        return response;
    }


    @RequestMapping(value = "/vchat", produces = "text/html;charset=utf-8")
    public Flux<String> chat(@RequestParam("prompt") String prompt) {
        //根据字符串 生成一个Flux<String>对象
        if ("初始化开启".equals( prompt)){
          String str=""" 
                  请整理一下内容：
                  **主要内容**
                      - 长江智助星是一款AI赋能视频制作工具，可以帮你高效搭建数字人课程视频。提供了一站式备考、AI智能体答疑功能。
                      - **AI赋能视频制作工具**
                        - *核心定位*：通过人工智能技术简化视频制作流程，降低专业门槛。
                      - **一站式备考支持**
                        - *应用场景*：针对教育/考试需求，提供从课程制作到复习备考的全流程工具。
                      - **AI智能体答疑功能**
                        - *实时解答*用户在备考或课程学习中的问题（如题目解析、概念查询）。
             """;

            return vClient.prompt()
                    .user(str)
                    .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, "video"))
                    .stream()
                    .content();
        }


        Flux<String> response = vClient.prompt()
                .user(prompt)
                .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, "video"))
                .stream()
                .content();
        return response;
    }


    //获取练习题
    @GetMapping(value = "/getPractice")
    public   List<STVO> getPractice(@RequestParam("prompt") String prompt) {
//        USER_ANSWERS
        if("init".equals(prompt)){
            ChatClient.CallResponseSpec lxt = tClient.prompt()
                    .user(MindConstants.mind)
                    .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, "lxt"))
                    .call();
            String content = lxt.content();
            //从content 字符串 中截取<questions>标签之间的内容 封装成对象List<STVO>
            List<STVO> questions = new ArrayList<>();
            int start = content.indexOf("<questions>");
            int end = content.indexOf("</questions>");
            if (start != -1 && end != -1) {
                String questionString = content.substring(start + "<questions>".length(), end);
                System.out.println("questionString:"+questionString);
                questions = com.alibaba.fastjson.JSON.parseArray(questionString, STVO.class);
                System.out.println(questions.size());
            }
            return questions;
        }
        if("again".equals(prompt)){
            ChatClient.CallResponseSpec lxt = tClient.prompt()
                    .user("请重新生成一份试题")
                    .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, "lxt"))
                    .call();
            String content = lxt.content();
            //从content 字符串 中截取<questions>标签之间的内容 封装成对象List<STVO>
            List<STVO> questions = new ArrayList<>();
            int start = content.indexOf("<questions>");
            int end = content.indexOf("</questions>");
            if (start != -1 && end != -1) {
                String questionString = content.substring(start + "<questions>".length(), end);
                System.out.println("questionString:"+questionString);
                questions = com.alibaba.fastjson.JSON.parseArray(questionString, STVO.class);
                System.out.println(questions.size());
            }
            return questions;
        }
        return null;
    }
    //提交答案 方法
    @GetMapping(value = "/submitAnswer")
    public DAVO submitAnswer(@RequestParam("prompt") String prompt) {

        String  response= tClient.prompt()
                .user("用户的答案:"+prompt+"请评估")
                .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, "lxt"))
                 .call().content();
        DAVO davo = new DAVO();
// 提取 <思考> 内容
        String thinking = extractContent(response, "<思考>(.*?)</思考>");
        davo.setAnalysis( thinking);

// 提取 <score> 内容
        String score = extractContent(response, "<score>(.*?)</score>");
        davo.setScore(Integer.parseInt(score));
// 提取 <analysis> 内容
        String analysis = extractContent(response, "<analysis>(.*?)</analysis>");
        davo.setText(analysis);
         return  davo;
    }
    // 方法定义
    private String extractContent(String text, String regex) {
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regex, java.util.regex.Pattern.DOTALL);
        java.util.regex.Matcher matcher = pattern.matcher(text);
        if (matcher.find()) {
            return matcher.group(1).trim();
        }
        return null;
    }
}
